/*
 * System.c
 *
 *  Created on: 2022��3��11��
 *      Author: TangJie
 */

#include "System.h"



const uint8_t g_u8SoftwareVersion[2]={0xBD, 0x01};

static const uint16_t g_dnpCrcTable[256u] = {
0x0000, 0x365e, 0x6cbc, 0x5ae2, 0xd978, 0xef26, 0xb5c4, 0x839a,
0xff89, 0xc9d7, 0x9335, 0xa56b, 0x26f1, 0x10af, 0x4a4d, 0x7c13,
0xb26b, 0x8435, 0xded7, 0xe889, 0x6b13, 0x5d4d, 0x07af, 0x31f1,
0x4de2, 0x7bbc, 0x215e, 0x1700, 0x949a, 0xa2c4, 0xf826, 0xce78,
0x29af, 0x1ff1, 0x4513, 0x734d, 0xf0d7, 0xc689, 0x9c6b, 0xaa35,
0xd626, 0xe078, 0xba9a, 0x8cc4, 0x0f5e, 0x3900, 0x63e2, 0x55bc,
0x9bc4, 0xad9a, 0xf778, 0xc126, 0x42bc, 0x74e2, 0x2e00, 0x185e,
0x644d, 0x5213, 0x08f1, 0x3eaf, 0xbd35, 0x8b6b, 0xd189, 0xe7d7,
0x535e, 0x6500, 0x3fe2, 0x09bc, 0x8a26, 0xbc78, 0xe69a, 0xd0c4,
0xacd7, 0x9a89, 0xc06b, 0xf635, 0x75af, 0x43f1, 0x1913, 0x2f4d,
0xe135, 0xd76b, 0x8d89, 0xbbd7, 0x384d, 0x0e13, 0x54f1, 0x62af,
0x1ebc, 0x28e2, 0x7200, 0x445e, 0xc7c4, 0xf19a, 0xab78, 0x9d26,
0x7af1, 0x4caf, 0x164d, 0x2013, 0xa389, 0x95d7, 0xcf35, 0xf96b,
0x8578, 0xb326, 0xe9c4, 0xdf9a, 0x5c00, 0x6a5e, 0x30bc, 0x06e2,
0xc89a, 0xfec4, 0xa426, 0x9278, 0x11e2, 0x27bc, 0x7d5e, 0x4b00,
0x3713, 0x014d, 0x5baf, 0x6df1, 0xee6b, 0xd835, 0x82d7, 0xb489,
0xa6bc, 0x90e2, 0xca00, 0xfc5e, 0x7fc4, 0x499a, 0x1378, 0x2526,
0x5935, 0x6f6b, 0x3589, 0x03d7, 0x804d, 0xb613, 0xecf1, 0xdaaf,
0x14d7, 0x2289, 0x786b, 0x4e35, 0xcdaf, 0xfbf1, 0xa113, 0x974d,
0xeb5e, 0xdd00, 0x87e2, 0xb1bc, 0x3226, 0x0478, 0x5e9a, 0x68c4,
0x8f13, 0xb94d, 0xe3af, 0xd5f1, 0x566b, 0x6035, 0x3ad7, 0x0c89,
0x709a, 0x46c4, 0x1c26, 0x2a78, 0xa9e2, 0x9fbc, 0xc55e, 0xf300,
0x3d78, 0x0b26, 0x51c4, 0x679a, 0xe400, 0xd25e, 0x88bc, 0xbee2,
0xc2f1, 0xf4af, 0xae4d, 0x9813, 0x1b89, 0x2dd7, 0x7735, 0x416b,
0xf5e2, 0xc3bc, 0x995e, 0xaf00, 0x2c9a, 0x1ac4, 0x4026, 0x7678,
0x0a6b, 0x3c35, 0x66d7, 0x5089, 0xd313, 0xe54d, 0xbfaf, 0x89f1,
0x4789, 0x71d7, 0x2b35, 0x1d6b, 0x9ef1, 0xa8af, 0xf24d, 0xc413,
0xb800, 0x8e5e, 0xd4bc, 0xe2e2, 0x6178, 0x5726, 0x0dc4, 0x3b9a,
0xdc4d, 0xea13, 0xb0f1, 0x86af, 0x0535, 0x336b, 0x6989, 0x5fd7,
0x23c4, 0x159a, 0x4f78, 0x7926, 0xfabc, 0xcce2, 0x9600, 0xa05e,
0x6e26, 0x5878, 0x029a, 0x34c4, 0xb75e, 0x8100, 0xdbe2, 0xedbc,
0x91af, 0xa7f1, 0xfd13, 0xcb4d, 0x48d7, 0x7e89, 0x246b, 0x1235,
};


const static tBootInfo gs_stBootInfo = {
	16u,    /*Exchange inforamtion length must N * 4.*/
	0x5Au,
	0xA5u,
	0x200037F0u,
	0x200037F1u,
	0x200037F0u,
};

/*get information storage CRC*/
#define GetInfoStorageCRC() (*(uint16_t*)(gs_stBootInfo.infoStartAddr + 14))

/*set information CRC */
#define SetInforCRC(xCrc) ((*(uint16_t*)(gs_stBootInfo.infoStartAddr + 14)) = (uint16_t)(xCrc))


//LinTxCompletedPara_t  g_stLINTxCompletedAction = {0x00, NULL};

/*
void LinDiag_SetTxAction(l_u8 pid, LinTxCompletedCallback pfact)
{
	g_stLINTxCompletedAction.u8LastPID = pid;
	g_stLINTxCompletedAction.TxCallback = pfact;
}

void LinDiag_ClearTxAction()
{
	g_stLINTxCompletedAction.u8LastPID = 0;
	g_stLINTxCompletedAction.TxCallback = NULL;
}
*/

static void Sys_CreatCrc16(const uint8_t *i_pDataBuf, const uint32_t i_dataLen, uint16_t *m_pCurCrc)
{
    uint16_t crc = 0u;
    uint32_t ret = 0;
    uint32_t index = 0u;
    for(index = 0u; index < i_dataLen; index++)
    {
        crc = ( crc >> 8 ) ^ g_dnpCrcTable[( crc ^ i_pDataBuf[index]) & 0x00ff] ;
    }

    ret = (uint32_t)((~crc) & 0xFFFFu);
    *m_pCurCrc = (uint16_t)ret;
}

void Sys_SetRAMProgramFlag()
{
//	*((uint32_t*)DOWNLOAD_REQUEST_FLAG_ADD) = DOWNLOAD_REQUEST_FLAG;
	uint16_t infoCrc = 0u;

	*((uint8_t*)gs_stBootInfo.requestEnterBootloaderAddr) = gs_stBootInfo.requestEnterBootloader;

	Sys_CreatCrc16((const uint8_t *)gs_stBootInfo.infoStartAddr, gs_stBootInfo.infoDataLen - 2u, &infoCrc);

	SetInforCRC(infoCrc);
}

void Sys_ClearRAMProgramFlag()
{
	*((uint32_t*)DOWNLOAD_REQUEST_FLAG_ADD) = 0;
}

/*
void DiagService_SessionControl(l_u8 NAD)
{
	lin_tl_pdu_data_t RxPdu;
	lin_tl_pdu_data_t TxPdu;
	if(ld_raw_rx_status(LI0) == LD_DATA_AVAILABLE)
	{
		ld_get_raw(LI0, RxPdu);
		switch((RxPdu[3]&0x0F))
		{
		case SESSION_DEFAULT:
			if((RxPdu[0] == NAD) ||(RxPdu[0] == LD_FUNCTIONAL_NAD))
			{
				if((RxPdu[3]&0x80) !=0x80)
				{
					TxPdu[0] = SERVICE_SESSION_CONTROL + 0x40;;
					TxPdu[1] = SESSION_DEFAULT;
					ld_send_message(LI0, 2, NAD, TxPdu);
				}
			}
			break;
		case SESSION_PROGRAM:
			if(RxPdu[0] == LD_BROADCAST)
			{
				Sys_SetRAMProgramFlag();
				MCU_SystemReset();
			}else if((RxPdu[0] == NAD) ||(RxPdu[0] == LD_FUNCTIONAL_NAD))
			{
				if((RxPdu[3]&0x80) !=0x80)
				{
					TxPdu[0] = SERVICE_SESSION_CONTROL + 0x40;;
					TxPdu[1] = SESSION_PROGRAM;
					ld_send_message(LI0, 2, NAD, TxPdu);
				}
				Sys_SetRAMProgramFlag();
				LinDiag_SetTxAction(0x3D, MCU_SystemReset);
			}
			break;
		case SESSION_EXTEND:
			if((RxPdu[0] == NAD) ||(RxPdu[0] == LD_FUNCTIONAL_NAD))
			{
				if((RxPdu[3]&0x80) !=0x80)
				{
					TxPdu[0] = SERVICE_SESSION_CONTROL + 0x40;;
					TxPdu[1] = SESSION_EXTEND;
					ld_send_message(LI0, 2, NAD, TxPdu);
				}
			}
			break;
		default:
			break;
		}
	}
}

void DiagService_ReadDataByIdentify(l_u8 NAD)
{
	lin_tl_pdu_data_t RxPdu;
	lin_tl_pdu_data_t TxPdu;
	if(ld_raw_rx_status(LI0) == LD_DATA_AVAILABLE)
	{
		ld_get_raw(LI0, RxPdu);
	}
}

void LinDiag_MainFunction()
{
	l_u8 i;
	l_u16 StatusWord = 0;
    const lin_protocol_user_config_t * prot_user_config_ptr = &g_lin_protocol_user_cfg_array[LI0];
    lin_tl_descriptor_t * tl_desc_ptr = &g_lin_tl_descriptor_array[LI0];
    const lin_node_attribute_t * node_attr_ptr;
    node_attr_ptr = &g_lin_node_attribute_array[prot_user_config_ptr->slave_ifc_handle];
    if(lin_lld_get_state(LI0) == LIN_NODE_STATE_UNINIT)
    {
    	return;
    }
    StatusWord = l_ifc_read_status(LI0);
    if(ld_tx_status(LI0) == LD_COMPLETED)
    {
		if(g_stLINTxCompletedAction.TxCallback != NULL)
		{
			g_stLINTxCompletedAction.TxCallback();
		}
		LinDiag_ClearTxAction();
    }

    for (i = 0U; i < node_attr_ptr->number_support_sid; i++)
    {
        if(diag_get_flag(LI0, i) == 1)
        {
        	switch(node_attr_ptr->service_supported_ptr[i])
        	{
        	case SERVICE_SESSION_CONTROL:
          		DiagService_SessionControl(*(node_attr_ptr->configured_NAD_ptr));
        		break;
        	case SERVICE_IO_CONTROL_BY_IDENTIFY:
        		break;
        	case SERVICE_READ_DATA_BY_IDENTIFY:
        		DiagService_ReadDataByIdentify(*(node_attr_ptr->configured_NAD_ptr));
        		break;
        	case SERVICE_WRITE_DATA_BY_IDENTIFY:
        		break;
        	default:
        		break;
        	}
        	diag_clear_flag(LI0, i);
        }
    }
}

l_u8 ld_read_by_id_callout(l_ifc_handle iii, l_u8 id, l_u8 *data)
{
    l_u8 retval = LD_NEGATIVE_RESPONSE;

     Get the current configuration
    const lin_protocol_user_config_t  *prot_user_config_ptr = &g_lin_protocol_user_cfg_array[iii];

    if (prot_user_config_ptr->function == (bool)LIN_SLAVE)
    {
         Following code is an example - Real implementation is application-dependent
         the handling does essentially depend on the id of the requested item
         This example implement with ID = 32 - LIN_READ_USR_DEF_MIN
        if (id == LIN_READ_USR_DEF_MIN)
        {

        }
        else if(id == LIN_READ_SW_VERSION)
        {
			data[0] = g_u8SoftwareVersion[0];
			data[1] = g_u8SoftwareVersion[1];
			retval = LD_POSITIVE_RESPONSE;
        }
    }  End (conf->function == _SLAVE_)
   return retval;
}
*/
